﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Selenium.PageToolkit.ControlFactoryChainImpl
{
    internal class ControlCollectionFactory : ChainBase<PageElementAttribute>
    {
        protected override object Inject(Type fieldType, PageElementAttribute attribute, LambdaPageFactory factory)
        {
            if (!IsAGenericList(fieldType))
                return null;
            var rowType = fieldType.GetGenericArguments()[0];
            if (rowType.GetConstructor(new Type[0]) == null)
                return null;
            //Yo dawh, I've heard you like lambdas! So I've put lambda inside lambda, which calls other lambda inside lambda recurrently.
            Func<IEnumerable<object>> generatorFunc = () => factory.DriverFactory().FindElements(attribute.Spec()).Select(e =>
                {
                    var inst = Activator.CreateInstance(rowType);
                    new LambdaPageFactory { DriverFactory = () => e }.Inject(inst);
                    return inst;
                });
            var interceptor = new WebElementCollectionInterceptor(generatorFunc, rowType);
            var listType = typeof(IList<>).MakeGenericType(rowType);
            return LambdaPageFactory.Generator.CreateInterfaceProxyWithoutTarget(listType, interceptor);
        }

        private bool IsAGenericList(Type fieldType)
        {
            if (!fieldType.IsGenericType)
                return false;
            var targetType = typeof(IList<>).MakeGenericType(fieldType.GetGenericArguments()[0]);
            if (fieldType.IsAssignableFrom(targetType))
                return true;
            return false;
        }

    }
}